import axios from 'axios'

class Axioser {
  /**
   * Axioser Constructor
   * @param {object} config
   */
  constructor(config) {
    this.instance = axios.create(config)

    /**
     * 请求拦截器
     */
    this.instance.interceptors.request.use(
      this.requestUseFulfilled.bind(this),
      this.requestUseRejected.bind(this)
    )

    /**
     * 响应拦截器
     */
    this.instance.interceptors.response.use(
      this.responseUseFulfilled.bind(this),
      this.responseUseRejected.bind(this)
    )
  }

  // 抽象方法 requestUseFulfilled，子类应该覆盖
  async requestUseFulfilled(config) {
    return config
  }

  // 抽象方法 requestUseRejected，子类应该覆盖
  async requestUseRejected(error) {
    return Promise.reject(error)
  }

  // 抽象方法 responseUseFulfilled，子类应该覆盖
  async responseUseFulfilled(response) {
    return response
  }

  // 抽象方法 responseUseRejected，子类应该覆盖
  async responseUseRejected(error) {
    return Promise.reject(error)
  }

  // 抽象方法 responseError，子类选择覆盖，不需要任何返回值
  async responseError(error) {
    console.error('请求响应异常：', error)
  }

  async request(config) {
    try {
      return await this.instance.request(config)
    } catch (error) {
      // error === throw AxiosError(code, config, message, name, request, response, stack)
      // 这里是所有请求响应异常拦截，可以做上报和埋点
      // 已执行全局拦截器： responseUseRejected(error)，同步
      // 再执行派生类请求响应异常方法： responseError(error)，异步，不需要任何返回值
      await this.responseError(error)
      // if (error.response.status >= 500) {
      //   // 一般是服务器错误，停止或者维护，直接抛出异常，禁止用户任何操作
      //   throw new Error('stop')
      // }
    }
  }

  /**
   * get 请求
   * @param {string} url
   * @param {object} params
   * @param {object} config
   * @returns
   */
  async get(url, params, config) {
    return await this.request({
      method: 'get',
      url,
      params,
      ...config
    })
  }

  /**
   * post 请求
   * @param {string} url
   * @param {object} data
   * @param {object} config
   * @returns
   */
  async post(url, data, config) {
    return await this.request({
      method: 'post',
      url,
      data,
      ...config
    })
  }

  /**
   * put 请求
   * @param {string} url
   * @param {object} data
   * @param {object} config
   * @returns
   */
  async put(url, data, config) {
    return await this.request({
      method: 'put',
      url,
      data,
      ...config
    })
  }

  /**
   * delete 请求
   * @param {string} url
   * @param {object} params
   * @param {object} headers
   * @returns
   */
  async delete(url, params, config) {
    return await this.request({
      method: 'delete',
      url,
      params,
      ...config
    })
  }
}

export default Axioser
